package org.xiyu.yee.beacon_anti_phantom.mixin;

import net.minecraft.core.BlockPos;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.monster.Phantom;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.xiyu.yee.beacon_anti_phantom.beacon.BeaconManager;
import org.xiyu.yee.beacon_anti_phantom.Constants;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Mixin(ServerChunkCache.class)
public class ServerChunkCacheMixin {
    
    @Shadow @Final ServerLevel level;
    
    // 使用更简单的数据结构，避免内部类问题
    private final Map<UUID, Phantom> attackingPhantoms = new ConcurrentHashMap<>();
    private final Map<UUID, BlockPos> attackingBeacons = new ConcurrentHashMap<>();
    private final Map<UUID, Long> attackStartTimes = new ConcurrentHashMap<>();
    
    @Inject(method = "tickChunks", at = @At("TAIL"))
    private void removePhantomInBeaconRange(CallbackInfo ci) {
        // 处理正在攻击的幻翼
        this.processAttackingPhantoms();
        
        // 检查新的幻翼
        this.level.getAllEntities().forEach(entity -> {
            if (entity instanceof Phantom phantom) {
                UUID phantomId = phantom.getUUID();
                
                // 如果已经在攻击中，跳过
                if (this.attackingPhantoms.containsKey(phantomId)) {
                    return;
                }
                
                BlockPos pos = phantom.blockPosition();
                if (BeaconManager.getInstance().isInBeaconRange(pos)) {
                    // 找到最近的信标并开始攻击
                    BlockPos nearestBeacon = this.findNearestBeacon(pos);
                    if (nearestBeacon != null) {
                        Constants.LOG.info("Starting beacon attack on phantom {} from beacon at {}", phantomId, nearestBeacon);
                        this.attackingPhantoms.put(phantomId, phantom);
                        this.attackingBeacons.put(phantomId, nearestBeacon);
                        this.attackStartTimes.put(phantomId, System.currentTimeMillis());
                    }
                }
            }
        });
    }
    
    private void processAttackingPhantoms() {
        Iterator<Map.Entry<UUID, Phantom>> iterator = this.attackingPhantoms.entrySet().iterator();
        
        while (iterator.hasNext()) {
            Map.Entry<UUID, Phantom> entry = iterator.next();
            UUID phantomId = entry.getKey();
            Phantom phantom = entry.getValue();
            
            // 检查幻翼是否还存在
            if (phantom.isRemoved()) {
                iterator.remove();
                this.attackingBeacons.remove(phantomId);
                this.attackStartTimes.remove(phantomId);
                continue;
            }
            
            BlockPos beaconPos = this.attackingBeacons.get(phantomId);
            Long startTime = this.attackStartTimes.get(phantomId);
            
            if (beaconPos == null || startTime == null) {
                iterator.remove();
                this.attackingBeacons.remove(phantomId);
                this.attackStartTimes.remove(phantomId);
                continue;
            }
            
            long currentTime = System.currentTimeMillis();
            long elapsedTime = currentTime - startTime;
            
            // 生成粒子束效果
            this.spawnBeamParticles(beaconPos, phantom.position());
            
            // 1秒后移除幻翼
            if (elapsedTime >= 1000) {
                Constants.LOG.info("Beacon attack complete! Removing phantom {} after {}ms", phantomId, elapsedTime);
                phantom.discard();
                iterator.remove();
                this.attackingBeacons.remove(phantomId);
                this.attackStartTimes.remove(phantomId);
            }
        }
    }
    
    private void spawnBeamParticles(BlockPos beaconPos, Vec3 phantomPos) {
        Vec3 beaconVec = Vec3.atCenterOf(beaconPos);
        Vec3 direction = phantomPos.subtract(beaconVec).normalize();
        double distance = beaconVec.distanceTo(phantomPos);
        
        // 沿着直线生成粒子
        int particleCount = (int) Math.max(15, distance * 1.5);
        for (int i = 0; i < particleCount; i++) {
            double progress = (double) i / particleCount;
            Vec3 particlePos = beaconVec.add(direction.scale(distance * progress));
            
            // 使用发光的粒子效果
            this.level.sendParticles(ParticleTypes.END_ROD, 
                particlePos.x, particlePos.y, particlePos.z, 
                1, 0.0, 0.0, 0.0, 0.0);
            
            // 添加一些装饰性粒子
            if (i % 2 == 0) {
                this.level.sendParticles(ParticleTypes.ELECTRIC_SPARK, 
                    particlePos.x, particlePos.y, particlePos.z, 
                    2, 0.1, 0.1, 0.1, 0.05);
            }
        }
        
        // 在幻翼位置生成爆炸效果粒子
        this.level.sendParticles(ParticleTypes.CRIT, 
            phantomPos.x, phantomPos.y, phantomPos.z, 
            8, 0.3, 0.3, 0.3, 0.1);
            
        // 添加更多视觉效果
        this.level.sendParticles(ParticleTypes.FLAME, 
            phantomPos.x, phantomPos.y, phantomPos.z, 
            3, 0.2, 0.2, 0.2, 0.02);
    }
    
    private BlockPos findNearestBeacon(BlockPos phantomPos) {
        BlockPos nearestBeacon = null;
        double nearestDistance = Double.MAX_VALUE;
        
        for (Map.Entry<BlockPos, Integer> entry : BeaconManager.getInstance().getActiveBeacons().entrySet()) {
            BlockPos beaconPos = entry.getKey();
            double distance = Math.sqrt(Math.pow(phantomPos.getX() - beaconPos.getX(), 2) + 
                                      Math.pow(phantomPos.getZ() - beaconPos.getZ(), 2));
            
            int radius = BeaconManager.getInstance().getBeaconRadius(beaconPos);
            if (distance <= radius && distance < nearestDistance) {
                nearestDistance = distance;
                nearestBeacon = beaconPos;
            }
        }
        
        return nearestBeacon;
    }
}
